/// 尝试使用 RefCell 来绕开借用规则


pub trait Messenger {
    fn send(&self, msg: &str);
}

pub struct LimitTracker <'a, T: 'a + Messenger> {
    messenger : &'a T,
    value: usize,
    max: usize,
}

impl <'a, T> LimitTracker<'a, T>
    where T:Messenger
{
    pub fn new(messenger: &T, max: usize) -> LimitTracker<T> {
        LimitTracker {
            messenger,
            value: 0,
            max,
        }
    }

    pub fn set_value(&mut self, value: usize) {
        self.value = value;
        let percentage_of_max = self.value as f64 / self.max as f64;
        if(percentage_of_max >= 1.0) {
            self.messenger.send("Error: You are over your quota!");
        } else if percentage_of_max >= 0.9 {
            self.messenger.send("Urgent warning: You're used up over 90% of your quota!");
        } else if percentage_of_max >= 0.75 {
            self.messenger.send("Warning: You're used up over 75% of your quota!");
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::cell::RefCell;

    // 创建一个Messager 的Mock 类用于测试
    struct MockMessenger {
        send_messages: RefCell<Vec<String>>,
    }

    impl MockMessenger {
        fn new() -> MockMessenger {
            MockMessenger {
                // 注意这里面必须是 RefCell::new 否则的话下面实现 Messenger 接口的时候，给 send_messages push 值时就会出现不能更改不可变变量的问题
                send_messages: RefCell::new(vec![])
            }
        }
    }

    // 给MockMessenger 的测试类实现 Messenger 的trait
    impl Messenger for MockMessenger {
        fn send(&self, message: &str) {
            // self.send_messages.push(String::from(message)); 这不行了，而且不能变成 &mnt self 这会造成与trait 定义不符
            // 于是乎 RefCell 的强大之处就在于 borrow_mut()
            self.send_messages.borrow_mut().push(String::from(message));
        }
    }

    #[test]
    fn it_sends_an_over_75_percent_warning_message() {
        let mock_messager: MockMessenger = MockMessenger::new();
        assert_eq!(mock_messager.send_messages.borrow().len(), 0 , "调用borrow() 方法获取借用，这个Vec里面是空的所以 count=0 ");
        let mut limit_tracker = LimitTracker::new(&mock_messager, 100);
        limit_tracker.set_value(80);
        assert_eq!(mock_messager.send_messages.borrow().len(), 1 , "因为调用了LimitTracker.set_value所以send_messages 的 Vec 元素就变成1了。");
    }
}